Profiling mechanisms are used on a regular basis in the software industry to aid in the development of more efficient programs. With a profiling mechanism, it is possible to ascertain how much processing time is being spent on each part of a program. Armed with this information, a software developer can locate bottlenecks in the program, and can revise the code in the bottlenecks to make the program run more efficiently.
In a typical profiling mechanism, profiling is carried out using a log and a timer. More specifically, as each operation of a program is executed, a timer is started. When the operation completes execution, the timer is stopped. From the start time and the end time, the processing time of the operation is determined, and the processing time is recorded in the log in association with the operation. By doing this for all of the operations that are executed in the program, the profiling mechanism derives a complete execution profile for the program, which includes a list of all of the operations that were executed, and the total amount of time spent on executing each operation.
Typically, a profiling mechanism (which usually takes the form of a set of program code) is executed on the same machine as the program that is being profiled. Thus, in order for the profiling mechanism to work properly, that machine needs to have a timer that the profiling mechanism can invoke to time the execution of the operations.
In a profiling mechanism that profiles object-oriented programs, an operation goes down as far as the method level. Thus, whenever a method is invoked, a timer is started. When the method returns, the timer is stopped. Based upon the start time and the end time, the profiling mechanism determines how much processing time was consumed by the method. The processing time is thereafter recorded in the log in association with the method. This is done each time a method is invoked. Thus, by the end of program execution, the profiling mechanism has a list of all of the methods that were invoked, and the total amount of processing time spent on each method.
The profiling methodology discussed above is effective for some implementations; however, for many other implementations, it has a number of significant drawbacks. A first drawback is that, in order to be accurate, the methodology requires a timer with a high degree of precision. Since some methods can be quite simple and hence, can be executed in a very short period of time (e.g. microseconds), the timer needs to have a high degree of precision in order for the profile to be accurate. As noted above, the profiling mechanism is typically executed on the same machine as the program that is being profiled. This means that that machine needs to have a timer with a high degree of precision. If the machine is a low cost or low capability device (such as a cellular phone or a personal digital assistant (PDA)), it may not have such a high precision timer. In that case, the profile derived from running the profiling mechanism on that machine will not be very accurate or useful.
Another shortcoming of the above methodology is that the overhead of starting and stopping the timer each time a method is invoked can add significant error to the profiling results. For example, if a method takes only 50 microseconds to run but the overhead of starting and stopping the timer is itself 50 microseconds, then the profiling mechanism will indicate that the method took 100 (rather than 50) microseconds to run, which represents a 100% error. Many methods in a program can be fast-executing methods; thus, the error caused by the timer overhead can have a substantial impact on the profile results.
Yet another shortcoming is that even if the profile results are completely accurate, they may still not be very useful to a developer. As noted above in connection with the discussion on object-oriented programs, current profiling mechanisms only provide profiling information down to the method level. They do not go as low as the source code line level. As a result, if a particular method having a large number of lines of code is identified as being a bottleneck in the program, the developer still does not have a good idea of what is causing the bottleneck. He knows that the cause is within that method, but he does not know which lines of code represent the source of the problem. As a result, the developer may still need to do a large amount of experimentation before he can isolate and eliminate the cause of the bottleneck.
From the above discussion, it is clear that the current profiling methodology leaves much to be desired. As a result, an improved computer code profiling methodology is needed.